<?php defined('SYSPATH') or die('No direct access allowed.');

class Model_Spot_Ticket_Price extends ORM
{

    /**
     * 获取当前时间的报价
     * @param $suitid
     * @param $timeStamp
     * @return array
     */
    public static function current_price($suitid, $timeStamp)
    {
        $arr  = DB::select()->from('spot_ticket_price')
            ->where("ticketid=$suitid")
            ->and_where('day', '=', $timeStamp)
            ->and_where('number', '!=', 0)
            ->and_where('supplier_channel_id', '=', 1)
            ->execute()->current();
        $data = !empty($arr) ? $arr : array();
        if (isset($data['adultprice'])) {
            $data['price'] = Currency_Tool::price($data['adultprice']);
        }
        return $data;
    }

    /**
     * 获取最近几天的报价
     * @param $suitid
     * @param $row 获取几天的数据
     * @return array
     */
    public static function get_next_price($suit, $row = 2)
    {
        $suitid   = $suit['id'];
        $cur_time = time();
        $sql      = "select a.* from sline_spot_ticket_price a left join sline_spot_ticket b on a.ticketid=b.id ";
        $sql      .= " where a.ticketid='{$suitid}' and a.number!=0  and a.supplier_channel_id=1 ";
        $sql      .= " and a.day>({$cur_time}+b.day_before*24*3600-case when (b.hour_before=0 and b.minute_before=0) then 24*3600 else (3600*b.hour_before+b.minute_before*60) end) limit {$row}";
        $arr      = DB::query(Database::SELECT, $sql)->execute()->as_array();
        foreach ($arr as &$data) {
            $data = !empty($data) ? $data : array();
            if (isset($data['adultprice'])) {
                $data['price'] = Currency_Tool::price($data['adultprice']);
            }
            $data['date'] = date('Y-m-d', $data['day']);
        }
        return $arr;
    }

    /**
     * @function 返回套餐报价状态
     * @param $suitid 套餐ID
     * @return int 3:没有报价('电询'),2:有报价,订完,1:可预订
     */
    public static function get_price_status($suit)
    {
        $suitid = $suit['id'];
        $day    = strtotime(date('Y-m-d', time() + intval($suit["day_before"]) * 24 * 3600));
        $arr    = DB::select()->from('spot_ticket_price')
            ->where("ticketid=$suitid")
            ->and_where('day', '>=', $day)
            ->and_where('supplier_channel_id', '=', 1)
            ->execute()->as_array();
        //存在报价
        if (!empty($arr)) {
            //有库存
            $arr2 = DB::select()->from('spot_ticket_price')
                ->where("ticketid=$suitid")
                ->and_where('day', '>=', $day)
                ->and_where('number', '!=', 0)
                ->and_where('supplier_channel_id', '=', 1)
                ->execute()->as_array();
            return empty($arr2) ? 2 : 1;
        }
        //没有报价
        return 3;
    }

    /**
     * 通过规格id删除价格
     * @param array $sku_ids
     * @return void
     */
    public static function del_by_sku(array $sku_ids)
    {
        DB::delete('spot_ticket_price')->where('sku_id', 'in', $sku_ids)->execute();
    }

    /**
     * 获取景点价格日历
     * @param $spot_id
     * @param $params
     * @return array
     */
    public static function get_spot_price_calendar($spot_id, $params)
    {
        $skus = Model_Spot_Ticket_Sku::get_price_sku($spot_id, $params);

        // 获取价格
        if (!empty($skus)) {
            $start_date = Arr::get($params, 'start_date', '');
            $start_date = $start_date ?: date('Y-m-d');
            $day_num    = Arr::get($params, 'day_num', 30);
            $end_date   = date("Y-m-d", strtotime($start_date . ' +' . $day_num . ' days'));
            $end_time   = strtotime($end_date);

            // 基础日期
            $base_times = array();
            for ($i = 0; ; $i++) {
                $current_date = date('Y-m-d', strtotime($start_date . ' +' . $i . ' days'));
                $time         = strtotime($current_date);
                if ($time > $end_time) {
                    break;
                }
                $base_times[] = $time;
            }

            $params['end_date'] = $end_date;
            foreach ($skus as &$sku) {
                $prices = self::get_price_calendar($spot_id, $sku, $params);
                $item   = array();
                foreach ($base_times as $base_time) {
                    $price  = $prices[$base_time] ?? '';
                    $item[] = array(
                        'date' => date("Y-m-d", $base_time),
                        'not_set' => !$price,
                        'price' => $price['price'] ?? '',
                        'basic_price' => $price['basic_price'] ?? '',
                        'stock' => $price['stock'] ?? '',
                        'is_open' => $price['is_open'] ?? 0,
                    );
                }
                $sku['price'] = $item;
            }
        }

        return $skus;
    }

    /**
     * 获取价格日历
     * @param $spot_id
     * @param $sku
     * @param array $params start_date:Y-m-d;end_date:Y-m-d;limit:number>0;is_open:number 1||0;
     * @return array
     */
    public static function get_price_calendar($spot_id, $sku, $params)
    {
        $start_date = Arr::get($params, 'start_date', '');
        $end_date   = Arr::get($params, 'end_date', '');

        $builder = DB::select(array('a.number', 'stock'), 'day', array('a.adultprice', 'price'), array('a.adultbasicprice', 'basic_price'), 'a.is_open')
            ->from(['spot_ticket_price', 'a'])
            ->join(['spot_ticket_stock', 'b'], 'left')
            ->on('a.ticketid', '=', DB::expr("sline_b.ticket_id"))
            ->where('a.spotid', '=', $spot_id);
        if (isset($sku['ticket_id'])) {
            $builder->and_where('a.ticketid', '=', $sku['ticket_id']);
        }
        if (!empty($sku['sku_id'])) {
            $builder->and_where('a.sku_id', '=', $sku['sku_id']);
        } else {
            if (isset($params['has_sku'])) {
                // 没有规格id时，根据是否包含规格获取价格
                if ($params['has_sku']) {
                    $builder->and_where('a.sku_id', '>', 0);
                } else {
                    $builder->and_where('a.sku_id', '=', 0);
                }
            }
        }
        if ($start_date) {
            $start_time = strtotime($start_date);
            $builder->and_where('a.day', '>=', $start_time);
        }
        if ($end_date) {
            $end_time = strtotime($end_date);
            $builder->and_where('a.day', '<=', $end_time);
        }
        if (isset($params['is_open'])) {
            $builder->and_where('a.is_open', '=', $params['is_open']);
        }
        if (isset($params['min_stock']) && $params['min_stock']) {
            $builder->and_where(DB::expr(" and (sline_a.number >= {$params['min_stock']} or sline_a.number = -1 OR sline_b.stock >0)"));
        }
        if (isset($params['rows']) && $params['rows']) {
            $builder->limit($params['rows']);
        }
        $list = $builder->group_by('day')->execute()->as_array('day');

        return self::total_stock_handle($list, $sku['ticket_id']);
    }

    /**
     * @param $list
     * @param $ticket_id
     * @return mixed
     * 检测是否有总库存 有的话就加上
     */
    public static function total_stock_handle($list, $ticket_id)
    {
        $total_stock = DB::select()->from('spot_ticket_stock')->where('ticket_id','=',$ticket_id)->execute()->as_array();
        if(count($total_stock)<1){
            return $list;
        }
        foreach ($list as &$v) {
            foreach ($total_stock as $stock) {
                if($v['day']>=$stock['start_day'] && $v['day']<=$stock['end_day']){
                    $v['stock'] = $stock['stock'];
                    break;
                }
            }
        }

        return $list;
    }


    /**
     * 批量保存
     * @param $spot_id
     * @param $params
     * @return void
     * @throws Exception
     */
    public static function save_batch_price($spot_id, $params)
    {
        $date_type = Arr::get($params, 'date_type', 1);

        // 处理日期
        if ($date_type == 'week') {
            // 按星期设置
            $date_start = Arr::get($params, 'date_type_week_start', '');
            $date_end   = Arr::get($params, 'date_type_week_end', '');

            $day_type = Arr::get($params, 'day_type', '');

            if (!$date_start || !$date_end) {
                throw new Exception('请设置日期范围');
            }

            $date_end_time = strtotime($date_end);
            $dates         = array();
            for ($i = 0; ; $i++) {
                $current_date = date('Y-m-d', strtotime($date_start . ' +' . $i . ' days'));
                $current_time = strtotime($current_date);
                if ($current_time > $date_end_time) {
                    break;
                }
                if (!empty($day_type) && $day_type[0] != 0) {
                    $week = date('N', $current_time);
                    if (!in_array($week, $day_type)) {
                        continue;
                    }
                }
                $dates[] = $current_time;
            }
        } else {
            // 按日期设置
            $date_type_date = Arr::get($params, 'date_type_date', '');
            $dates          = array();
            foreach ($date_type_date as $date) {
                $dates[] = strtotime($date);
            }
        }

        if (!empty($dates)) {
            //结算价类型
            $basic_price   = Arr::get($params, 'basic_price', '');
            $profit        = Arr::get($params, 'profit', '');
            //销售加类型
            $price         = Arr::get($params, 'basic_price', '');
            $stock_mod     = Arr::get($params, 'stock_mod', '');
            $stock         = Arr::get($params, 'stock', '');
            $warning_stock = Arr::get($params, 'warning_stock', '');
            $total_stock   = Arr::get($params, 'total_stock', '');

            $suit_list = Arr::get($params, 'suit_list', '');
            $suit_list = $suit_list ? explode(',', $suit_list) : '';
            $skus      = Model_Spot_Ticket_Sku::get_price_sku($spot_id);

            foreach ($skus as $sku) {
                if (!empty($suit_list)) {
                    if (!in_array($sku['tag'], $suit_list)) {
                        continue;
                    }
                }

                $price_tag         = $sku['ticket_id'] . '_' . $sku['sku_id'];
                $basic_price_money = $basic_price[$price_tag] ?? 0;
                $profit_money      = $profit[$price_tag] ?? 0;
                if ($sku['settlement_type'] == 2) {
                    $basic_price_money = $price[$price_tag] ?? 0;
                    $profit_money      = 0;
                }
                $price_data = array(
                    'basic_price'   => $basic_price_money,
                    'profit'        => $profit_money,
                    'stock_mod'     => $stock_mod[$price_tag] ?? 1,
                    'stock'         => $stock[$price_tag] ?? -1,
                    'warning_stock' => $warning_stock[$price_tag] ?? 0,
                    'source'        => 1
                );
                // 保存价格
                foreach ($dates as $date) {
                    self::save_one_price($spot_id, $sku, $date, $price_data);
                }
                if ($stock_mod[$price_tag] == 3) {
                    self::save_total_stock($dates, $sku, $total_stock[$price_tag], $spot_id);
                }else{
                    DB::delete('spot_ticket_stock')->where('ticket_id','=',$sku['ticket_id'])->execute();
                }
            }
        }
    }

    /**
     * @param $dates
     * @param $ticket
     * @param $total_stock
     * @return void
     * @throws Kohana_Exception
     * 存储时段总库存 会增删保证时段唯一性
     */
    public static function save_total_stock($dates, $ticket, $total_stock, $spot_id)
    {
        $ticket_id  = $ticket['ticket_id'];
        $start_day  = $dates[0];
        $end_day    = $dates[count($dates) - 1];
        $stock_info = DB::select()->from('spot_ticket_stock')->where('ticket_id', '=', $ticket_id)->execute()->as_array();

        $data = [
            'spot_id'   => $spot_id,
            'ticket_id' => $ticket_id,
            'start_day' => $start_day,
            'end_day'   => $end_day,
            'stock'     => $total_stock
        ];

        $to_be_deleted = [];

        // 遍历库存信息数组，检查是否存在时间重叠的库存信息
        foreach ($stock_info as $stock) {
            if ($start_day <= $stock['end_day'] && $end_day >= $stock['start_day']) {
                if ($start_day > $stock['start_day'] && $end_day < $stock['end_day']) {
                    // 时间范围在库存信息的中间部分，需要将库存信息拆分为两段
                    $to_be_deleted[] = $stock['id'];

                    $data1 = [
                        'ticket_id' => $ticket_id,
                        'start_day' => $stock['start_day'],
                        'end_day'   => bcsub($start_day, 86400),
                        'stock'    => $stock['stock']
                    ];

                    $data2 = [
                        'ticket_id' => $ticket_id,
                        'start_day' => bcadd($end_day, 86400),
                        'end_day'   => $stock['end_day'],
                        'stock'    => $stock['stock']
                    ];

                    // 插入两段拆分后的库存信息
                    DB::insert('spot_ticket_stock', array_keys($data1))->values(array_values($data1))->execute();
                    DB::insert('spot_ticket_stock', array_keys($data2))->values(array_values($data2))->execute();
                } elseif ($start_day > $stock['start_day']) {
                    // 更新库存信息的结束时间
                    DB::update('spot_ticket_stock')->set(['end_day' => bcsub($start_day, 86400)])->where('id', '=', $stock['id'])->execute();
                } elseif ($end_day < $stock['end_day']) {
                    // 更新库存信息的开始时间
                    DB::update('spot_ticket_stock')->set(['start_day' => bcadd($end_day, 86400)])->where('id', '=', $stock['id'])->execute();
                } else {
                    // 删除库存信息
                    $to_be_deleted[] = $stock['id'];
                }
            }
        }

        // 删除时间重叠部分的库存信息
        if (!empty($to_be_deleted)) {
            DB::delete('spot_ticket_stock')->where('id', 'IN', $to_be_deleted)->execute();
        }

        // 插入新的库存信息
        DB::insert('spot_ticket_stock', array_keys($data))->values(array_values($data))->execute();
    }

    /**
     * 保存单个价格
     * @param $spot_id
     * @param $sku Array( [ticket_id] => 3491 [sku_id] => 237 )
     * @param $date string 1703001600
     * @param $price_data Array ( [basic_price] => 123 [profit] => 33 [stock_mod] => 1 [stock] => 11 [warning_stock] =>  )
     * @return void
     * @throws Kohana_Exception
     */
    public static function save_one_price($spot_id, $sku, $date, $price_data)
    {
        /**
         * @var $basic_price
         * @var $profit
         * @var $stock_mod
         * @var $stock
         * @var $warning_stock
         * @var $total_stock
         */
        extract($price_data);

        $stock = $stock_mod == 2 ? -1 : ($stock_mod == 3 ? 0 : $stock);
        $orm       = ORM::factory('spot_ticket_price')
            ->where('spotid', '=', $spot_id)
            ->and_where('ticketid', '=', $sku['ticket_id'])
            ->and_where('sku_id', '=', $sku['sku_id'])
            ->and_where('day', '=', $date)
            ->find();
        $is_update = true;
        if (empty($orm->spotid)) {
            $is_update                = false;
            $orm                      = ORM::factory('spot_ticket_price');
            $orm->is_open             = 1;
            $orm->ticketid            = $sku['ticket_id'];
            $orm->spotid              = $spot_id;
            $orm->sku_id              = $sku['sku_id'];
            $orm->day                 = $date;
            $orm->supplier_channel_id = 1;
        }
        if (isset($price_data['is_open'])) {
            $orm->is_open = $price_data['is_open'] == 1 ? 1 : 0;
        }
        $orm->adultprofit     = $profit;
        $orm->adultbasicprice = $basic_price;
        $orm->number          = $stock;
        $orm->warning_stock   = $warning_stock;
        $orm->adultprice      = bcadd($profit, $basic_price, 2);
        $data                 = $orm->as_array();
        if ($is_update) {
            DB::update('spot_ticket_price')
                ->set($data)
                ->where('spotid', '=', $spot_id)
                ->and_where('ticketid', '=', $sku['ticket_id'])
                ->and_where('sku_id', '=', $sku['sku_id'])
                ->and_where('day', '=', $date)->execute();
        } else {
            DB::insert('spot_ticket_price', array_keys($data))->values(array_values($data))->execute();
        }

        if ($stock_mod == 3 && !$price_data['source']) {
            $org_stock = DB::select()->from('spot_ticket_stock')
                ->where('ticket_id','=',$sku['ticket_id'])
                ->and_where('start_day','<=',$date)
                ->and_where('end_day','>=',$date)
                ->execute()->get('stock');
            if(!$org_stock || $org_stock!=$total_stock){
                self::save_total_stock([$date,$date], $sku, $total_stock, $spot_id);
            }
        }
    }

    /**
     * 清除报价
     * @param $spot_id
     * @param $sku_id
     * @return void
     */
    public static function clear_price($spot_id, $sku_id = '')
    {
        $del_skus = array();
        if ($sku_id) {
            $sku_ids = explode(',', $sku_id);
            foreach ($sku_ids as $v) {
                $arr        = explode('-', $v);
                $del_skus[] = array('spot_id' => $spot_id, 'ticket_id' => $arr[0], 'sku_id' => $arr[1]);
            }
        } else {
            $del_skus[] = array('spot_id' => $spot_id);
        }
        foreach ($del_skus as $del_sku) {
            self::del($del_sku);
        }
    }

    /**
     * 删除价格
     * @param $params
     * @return void
     */
    public static function del($params = array())
    {
        $builder = DB::delete('spot_ticket_price');
        if (isset($params['spot_id'])) {
            $builder->where('spotid', '=', $params['spot_id']);
        }
        if (isset($params['ticket_id'])) {
            $builder->where('ticketid', '=', $params['ticket_id']);
        }
        if (isset($params['sku_id'])) {
            $builder->where('sku_id', '=', $params['sku_id']);
        }
        if (isset($params['day'])) {
            $day = strtotime($params['day']);
            $builder->where('day', '=', $day);
        }
        $builder->execute();

        if (!$params['day']) {
            $total_stock = DB::delete('spot_ticket_stock');
            if (isset($params['spot_id'])) {
                $total_stock->where('spot_id', '=', $params['spot_id']);
            }
            if (isset($params['ticket_id'])) {
                $total_stock->where('ticket_id', '=', $params['ticket_id']);
            }
            $total_stock->execute();
        }
    }

    /**
     * 获取报价，如果指定日期，返回一维数组
     * @param $params array('ticket_id' => $ticket_id,'sku_id' => $sku_id,'date' => $date, 'is_open'=> 1);
     * @return array|mixed|null
     */
    public static function get_price($params = array())
    {
        $builder = DB::select()->from('spot_ticket_price');
        if (isset($params['spot_id'])) {
            $builder->where('spotid', '=', $params['spot_id']);
        }
        if (isset($params['ticket_id'])) {
            $builder->where('ticketid', '=', $params['ticket_id']);
        }
        if (isset($params['sku_id'])) {
            $builder->where('sku_id', '=', $params['sku_id']);
        }
        if (isset($params['date'])) {
            $day = strtotime($params['date']);
            $builder->where('day', '=', $day);
        }
        if (isset($params['is_open'])) {
            $builder->where('is_open', '=', $params['is_open']);
        }
        if (isset($params['date'])) {
            $price = $builder->execute()->current();
            $total_stock = DB::select()->from('spot_ticket_stock')
                ->where('ticket_id', '=', $params['ticket_id'])
                ->and_where('start_day', '<=', strtotime($params['date']))
                ->and_where('end_day', '>=', strtotime($params['date']))
                ->execute()->current();
            if($total_stock){
                $price['number'] = $total_stock['stock'];
            }
            $price['stock_mod'] = (bool)$total_stock;
        } else {
            $price = $builder->execute()->as_array();
        }
        return $price;
    }

    /**
     * 更新价格状态
     * @param $ticket_id
     * @param $status
     * @param $params
     * @return void
     */
    public static function change_price_status($ticket_id, $status, $params = array())
    {
        $builder = DB::update('spot_ticket_price')
            ->where('ticketid', '=', $ticket_id)
            ->set(array('is_open' => $status));
        if (isset($params['sku_id'])) {
            $builder->where('sku_id', '=', $params['sku_id']);
        }
        if (isset($params['day'])) {
            $day = strtotime($params['day']);
            $builder->where('day', '=', $day);
        }
        $builder->execute();
    }

    /**
     * 景点报价有效期
     * @param $spot_id
     * @return int|mixed
     */
    public static function spot_expire_day($spot_id)
    {
        $day = DB::select(DB::expr("max(day) as day"))
            ->from('spot_ticket_price')
            ->where('spotid', '=', $spot_id)
            ->execute()
            ->get('day');

        if ($day) {
            return $day;
        }
        // 检查是否有套餐
        $check_suit = DB::select()
            ->from('spot_ticket')
            ->where('spotid', '=', $spot_id)
            ->execute()
            ->valid();

        return $check_suit ? '' : -1;
    }

    /**
     * 减库存
     * @param $order
     * @param $sku_id
     * @return bool
     */
    public static function sub_stock($order, $sku_id)
    {
        $suit_id = $order['suitid'];
        $num     = $order['dingnum'];
        $day     = strtotime($order['usedate']);

        $total_stock = DB::select()->from('spot_ticket_stock')
            ->where('ticket_id','=',$suit_id)
            ->and_where('start_day','<=',$day)
            ->and_where('end_day','>=',$day)
            ->execute()->get('stock');
        if($total_stock){
            if($total_stock<1 || $total_stock < $num){
                return false;
            }
            $update_arr = array(
                'stock' => DB::expr("stock - $num")
            );
            $query = DB::update('spot_ticket_stock')
                ->set($update_arr)
                ->where('ticket_id','=',$suit_id)
                ->and_where('start_day','<=',$day)
                ->and_where('end_day','>=',$day)
                ->execute();
            if(!$query){
                return false;
            }
        }else{
            $number = DB::select('number')
                ->from('spot_ticket_price')
                ->where('day', '=', $day)
                ->and_where('ticketid', '=', $suit_id)
                ->and_where('sku_id', '=', $sku_id)
                ->and_where('supplier_channel_id', '=', 1)
                ->execute()
                ->get('number');
            if (!$number) {
                return false;
            }

            // 无限库存不处理
            if ($number == -1) {
                return true;
            }

            $update_arr = array(
                'number' => DB::expr("number - $num")
            );

            $query = DB::update('spot_ticket_price')
                ->set($update_arr)
                ->where('day', '=', $day)
                ->and_where('ticketid', '=', $suit_id)
                ->and_where('sku_id', '=', $sku_id)
                ->execute();
            if (!$query) {
                return false;
            }
        }

        return true;
    }

    public static function save_settlement_data($params)
    {
        $settlement_key = Arr::get($params, 'settlement_key');
        $settlement_val = Arr::get($params, 'settlement_val');

        $data = [
            'type_id' => 5,
            'channel_id' => 1,
        ];
        foreach ($settlement_key as $k=>$v) {
            $ticket_id = explode('_',$k)[0];
            $data['suit_id'] = $ticket_id;
            $data['settlement_key'] = $v;
            $data['settlement_val'] = $v==1?$settlement_val[$k]/100:$settlement_val[$k];
            $id = DB::select()->from('supplier_settlement_config')
                ->where('suit_id','=',$ticket_id)
                ->and_where('type_id','=',5)
                ->execute()->get('id');
            if($id){
                DB::update('supplier_settlement_config')->set($data)->where('id','=',$id)->execute();
            }else{
                DB::insert('supplier_settlement_config', array_keys($data))->values(array_values($data))->execute();
            }
        }
    }
}
